//
//  main.m
//  OC2_实例变量可见度_方法
//
//  Created by dllo on 16/2/25.
//  Copyright © 2016年 Apon. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {

#pragma mark - 知识点1. 实例(成员)变量可见度
   /**
    * 3种: @public , @protected, @private.
    * 默认: @protected.
    *
    * 3种之间的区别: @public: 本类 可以直接访问(->).
                            子类 可以直接访问(->).
                            其他类 可以直接访问(->).
                   @protected: 本类 可以直接访问.
                               子类 可以直接访问.
                               其他类 不可以直接访问.
                   @private: 本类 可以直接访问.
                             子类 不可以直接访问.
                             其他类 不可以直接访问.
    * 详见 Person.h 文件 
    */
    
#pragma mark - 知识点2. 方法
  /** 
   * [接受者 消息]
   *
   * 接受者: 类和对象.
   * 消息(方法): 类方法(+)和对象方法(-).
   * 
   * 详见 Person.h文件.
   */

#if 0
#pragma mark - 知识点3. setter, getter 方法
/** 
 * 一个实例变量需要有一对setter, getter方法.
 * setter方法目的, 对实例变量赋值.
 * getter方法目的, 对实例变量取值.
 *
 * 详见 Person.h文件.
 */
    //创建p1对象.
    Person *p1 = [[Person alloc] init];
    [p1 setName:@"zhangsan"];
    [p1 name];
    NSString *str = [p1 name];
    NSLog(@"名字是:%@", str);
    
    //创建p2对象.
    Person *p2 = [[Person alloc] init];
    NSLog(@"%@", [p2 name]);
    p2.name = @"lisi";
    NSString *str1 = p2.name;
    NSLog(@"名字是:%@", str1);
    
    // 注意: 下面的p3并没有开辟新的内存空间只是指针指向了p2内存首地址.
    Person *p3 = p2;
    NSLog(@"%@", p3.name);
#pragma mark - 知识点4. 继承
    /**
     * 子类继承父类所有的实例变量和方法.
     * OC中只有子类和父类两层.
     * OC中是单向继承.
     * 继承有传递性.
     *
     * Student类继承于Person类, CollegeStudent类继承于Student类.
     * 详见 Student, CollegeStudent类文件.
     */
    
    // 创建学生对象.
    Student *s1 = [[Student alloc] init];
    
    // setName方法是从父类继承下来的方法.
    [s1 setName:@"小明"];
    
    [s1 name:@"小明" sex:@"male" age:18];
    
    [s1 sayHi];



#pragma mark - 知识点5. 重写父类方法(overwrite)

    /** 
     * 父类方法无法满足子类需求.
     * 重写父类方法一般是在父类方法的基础上,添加新的代码段.
     *
     * 详见 Student.m
     */
    
    // 创建Student对象.
    Student *student1 = [[Student alloc] init];
    [student1 name:@"wangwu" sex:@"male" age:20];
    [student1 setGrade:80];
    [student1 setclassroomName:@"DLS160101"];
    
    // 调用sayHi方法.
    [student1 sayHi];
    

    
#pragma mark - 知识点6. 重写初始化方法.
/** 
 * Person类 重写父类的init方法.
 * 详见 Person.m 文件.
 */
    // 创建一个person对象.
    
    Person *person1 = [[Person alloc] init];
    [person1 sayHi];
    
    
    // 创建student对象
    
    Student *stu = [[Student alloc] init];
    [stu sayHi];
    
#endif
    
#pragma mark - 知识点7. 自定义初始化方法.
/**
 * 需求: 通过一个方法, 实现了初始化, 同时给某些实例变量赋值.
 *
 * 详见 Person.h, person.m文件.
 */
    
    // 创建person对象
    Person *per1 = [[Person alloc]
    initWithName:@"tom"];
    [per1 sayHi];
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
}
